import { Injectable } from "@nestjs/common";

import { PrismaService } from "@/core/db/prisma.service";
import BusinessException from "@/core/exception/BusinessException";
import { PageResultVO } from "@/core/vo/page-result.vo";

import { CreateArticleDto } from "./dto/create-article.dto";
import { QueryArticleDto } from "./dto/query-article.dto";
import { UpdateArticleDto } from "./dto/update-article.dto";

@Injectable()
export class ArticleService {
    constructor(private readonly prismaService: PrismaService) {}

    create(createArticleDto: CreateArticleDto) {
        return this.prismaService.article.create({
            data: createArticleDto
        });
    }

    findAll() {
        return this.prismaService.article.findMany({ where: { isDeleted: false } });
    }

    async findPage(query: QueryArticleDto) {
        const {
            current,
            size,
            createdAtStart,
            createdAtEnd,
            updatedAtStart,
            updatedAtEnd,
            author,
            categoryId,
            excerpt,
            title
        } = query;
        const where = {
            isDeleted: false,
            createdAt: {
                gte: createdAtStart,
                lte: createdAtEnd
            },
            updatedAt: {
                gte: updatedAtStart,
                lte: updatedAtEnd
            },
            author,
            categoryId,
            excerpt: {
                contains: excerpt
            },
            title: {
                contains: title
            }
        };
        const [listData, total] = await Promise.all([
            this.prismaService.article.findMany({
                where,
                skip: (current - 1) * size,
                take: size,
                include: { Category: { select: { id: true, name: true } } }
            }),
            this.prismaService.article.count({
                where
            })
        ]);

        const pages = Math.ceil(total / size);
        return new PageResultVO(listData, total, pages, current, size);
    }
    findOne(id: number) {
        return this.prismaService.article.findUnique({
            where: { id, isDeleted: false },
            include: {
                Category: { select: { id: true, name: true } },
                Comments: {
                    where: { isDeleted: false, status: true },
                    include: { User: { select: { id: true, username: true, nickname: true, avatar: true } } }
                }
            }
        });
    }

    async update(id: number, updateArticleDto: UpdateArticleDto) {
        let res;
        try {
            res = await this.prismaService.article.update({
                where: {
                    id,
                    isDeleted: false
                },
                data: updateArticleDto
            });
        } catch (error) {
            throw new BusinessException();
        }
        return res;
    }

    async remove(id: number, softDelete: boolean = true) {
        try {
            if (softDelete) {
                await this.prismaService.article.update({
                    where: {
                        id,
                        isDeleted: false
                    },
                    data: {
                        isDeleted: true,
                        deletedAt: new Date()
                    }
                });
            } else {
                await this.prismaService.article.delete({
                    where: {
                        id,
                        isDeleted: false
                    }
                });
            }
        } catch (error) {
            throw new BusinessException();
        }
    }
}
